package hongcheng.code_generator.utils;

import java.sql.Types;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import hongcheng.code_generator.entity.JdbcTypeInformation;
import hongcheng.code_generator.exception.CustomException;



/**
 * 	通过数据库类型获取java类型的工具类
 * 	参考org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl的解决方案
 * */
public class DbType2JavaTypeUtils {
	
	/**
	 * 	key : 数据库类型名
	 * 	value: JdbcTypeInformation
	 * */
	private static volatile Map<String, JdbcTypeInformation> typeMap;
	
	static {
		typeMap = new HashMap<String, JdbcTypeInformation>();
		typeMap.put("ARRAY",
				new JdbcTypeInformation("ARRAY",Types.ARRAY, Object.class, Object.class.getName(), Object.class.getSimpleName()));
		typeMap.put("BIGINT",
				new JdbcTypeInformation("BIGINT",Types.BIGINT, Long.class, Long.class.getName(), Long.class.getSimpleName()));
		typeMap.put("BINARY",
				new JdbcTypeInformation("BINARY",Types.BINARY, null, "", "byte[]"));
		typeMap.put("BIT",
				new JdbcTypeInformation("BIT",Types.BIT, Boolean.class, Boolean.class.getName(), Boolean.class.getSimpleName()));
		typeMap.put("BLOB",
				new JdbcTypeInformation("BLOB",Types.BLOB, null, "", "byte[]"));
		typeMap.put("BOOLEAN",
				new JdbcTypeInformation("BOOLEAN",Types.BOOLEAN,Boolean.class, Boolean.class.getName(), Boolean.class.getSimpleName()));
		typeMap.put("CHAR",
				new JdbcTypeInformation("CHAR",Types.CHAR, String.class, String.class.getName(), String.class.getSimpleName()));
		typeMap.put("CLOB",
				new JdbcTypeInformation("CLOB",Types.CLOB, String.class, String.class.getName(), String.class.getSimpleName()));
		typeMap.put("DATALINK",
				new JdbcTypeInformation("DATALINK",Types.DATALINK, Object.class, Object.class.getName(), Object.class.getSimpleName()));
		typeMap.put("DATE",
				new JdbcTypeInformation("DATE",Types.DATE, Date.class, Date.class.getName(), Date.class.getSimpleName()));
		typeMap.put("DISTINCT",
				new JdbcTypeInformation("DISTINCT",Types.DISTINCT, Object.class, Object.class.getName(), Object.class.getSimpleName()));
		typeMap.put("DOUBLE",
				new JdbcTypeInformation("DOUBLE",Types.DOUBLE, Double.class, Double.class.getName(), Double.class.getSimpleName()));
		typeMap.put("FLOAT",
				new JdbcTypeInformation("FLOAT",Types.FLOAT, Double.class, Double.class.getName(), Double.class.getSimpleName()));
		typeMap.put("INTEGER",
				new JdbcTypeInformation("INTEGER",Types.INTEGER, Integer.class, Integer.class.getName(), Integer.class.getSimpleName()));
		typeMap.put("JAVA_OBJECT",
				new JdbcTypeInformation("JAVA_OBJECT",Types.JAVA_OBJECT, Object.class, Object.class.getName(), Object.class.getSimpleName()));
		typeMap.put("LONGNVARCHAR",
				new JdbcTypeInformation("LONGNVARCHAR",Types.LONGNVARCHAR, String.class, String.class.getName(), String.class.getSimpleName()));
		typeMap.put("LONGVARBINARY",
				new JdbcTypeInformation("LONGVARBINARY",Types.LONGVARBINARY, null, "", "byte[]"));
		typeMap.put("LONGVARCHAR",
				new JdbcTypeInformation("LONGVARCHAR",Types.LONGVARCHAR, String.class, String.class.getName(), String.class.getSimpleName()));
		typeMap.put("NCHAR",
				new JdbcTypeInformation("NCHAR",Types.NCHAR, String.class, String.class.getName(), String.class.getSimpleName()));
		typeMap.put("NCLOB",
				new JdbcTypeInformation("NCLOB",Types.NCLOB, String.class, String.class.getName(), String.class.getSimpleName()));
		typeMap.put("NVARCHAR",
				new JdbcTypeInformation("NVARCHAR",Types.NVARCHAR, String.class, String.class.getName(), String.class.getSimpleName()));
		typeMap.put("NULL",
				new JdbcTypeInformation("NULL",Types.NULL, Object.class, Object.class.getName(), Object.class.getSimpleName()));
		typeMap.put("OTHER",
				new JdbcTypeInformation("OTHER",Types.OTHER, Object.class, Object.class.getName(), Object.class.getSimpleName()));
		typeMap.put("REAL",
				new JdbcTypeInformation("REAL",Types.REAL,Float.class, Float.class.getName(), Float.class.getSimpleName()));
		typeMap.put("REF",
				new JdbcTypeInformation("REF",Types.REF, Object.class, Object.class.getName(), Object.class.getSimpleName()));
		typeMap.put("SMALLINT",
				new JdbcTypeInformation("SMALLINT",Types.SMALLINT, Short.class, Short.class.getName(), Short.class.getSimpleName()));
		typeMap.put("STRUCT",
				new JdbcTypeInformation("STRUCT", Types.STRUCT, Object.class, Object.class.getName(), Object.class.getSimpleName()));
		typeMap.put("TIME",
				new JdbcTypeInformation("TIME", Types.TIME, Date.class, Date.class.getName(), Date.class.getSimpleName()));
		typeMap.put("TIMESTAMP",
				new JdbcTypeInformation("TIMESTAMP", Types.TIMESTAMP, Date.class, Date.class.getName(), Date.class.getSimpleName()));
		typeMap.put("TINYINT",
				new JdbcTypeInformation("TINYINT", Types.TINYINT, Integer.class, Integer.class.getName(), Integer.class.getSimpleName()));
		typeMap.put("VARBINARY",
				new JdbcTypeInformation("VARBINARY", Types.VARBINARY, null, "", "byte[]"));
		typeMap.put("VARCHAR",
				new JdbcTypeInformation("VARCHAR", Types.VARCHAR, String.class, String.class.getName(), String.class.getSimpleName()));
		typeMap.put("VARCHAR2",
				new JdbcTypeInformation("VARCHAR2", Types.VARCHAR, String.class, String.class.getName(), String.class.getSimpleName()));
		typeMap.put("DECIMAL",
				new JdbcTypeInformation("DECIMAL", Types.DOUBLE, Double.class, Double.class.getName(), Double.class.getSimpleName()));
		typeMap.put("NUMERIC",
				new JdbcTypeInformation("NUMERIC", Types.DOUBLE, Double.class, Double.class.getName(), Double.class.getSimpleName()));
		typeMap.put("LONG",
				new JdbcTypeInformation("LONG", Types.LONGVARCHAR, String.class, String.class.getName(), String.class.getSimpleName()));
		typeMap.put("DATETIME",
				new JdbcTypeInformation("DATETIME", Types.TIMESTAMP, Date.class, Date.class.getName(), Date.class.getSimpleName()));
		typeMap.put("INT",
				new JdbcTypeInformation("INT", Types.INTEGER, Integer.class, Integer.class.getName(), Integer.class.getSimpleName()));
		typeMap.put("NUMBER",
				new JdbcTypeInformation("NUMBER", Types.NUMERIC, Double.class, Double.class.getName(), Double.class.getSimpleName()));
	}
	
	
	/***
	 * 	根据数据库的类型名，获取对应的JdbcTypeInformation
	 * */
	public static JdbcTypeInformation getJdbcTypeInformation(String dbFieldType) {
		// 因为MySQL的类型是有部分会带（）的，所以去掉括号
		if(dbFieldType.indexOf("(") != -1) {
			dbFieldType = dbFieldType.substring(0, dbFieldType.indexOf("("));
		}
		JdbcTypeInformation jdbcTypeInformation = typeMap.get(dbFieldType.toUpperCase());
		if(jdbcTypeInformation == null) {
			throw new CustomException("找不到{}这种类型对应的java类型信息。请添加{}这种类型添加进typeMap中，可使用本类的addType()方法进行添加",dbFieldType,dbFieldType) ;
		}
		return jdbcTypeInformation;
	}
	
	/***
	 * 	根据数据库的类型名，获取对应的JdbcTypeInformation
	 *  @param dbFieldType 数据库字段类型
	 *  @param jdbcTypeInformation 该数据库字段类型对应的java和jdbc类型
	 * */
	public static void addType(String dbFieldType,JdbcTypeInformation jdbcTypeInformation) {
		typeMap.put(dbFieldType, jdbcTypeInformation);
	}
	
	/***
	 * 	根据数据库的类型名，获取对应的JdbcTypeInformation
	 *  @param dbFieldType 数据库字段类型
	 * 	@param sqlType jdbc类型
	 * 	@param javaClasz 对应的java类型
	 * 	@param javaClassFullName 对应的java类完全限定名
	 * 	@param javaClassSimpleName 对应的java类型简单类名
	 * */
	public static void addType(String dbFieldType,int sqlType,Class<?> javaClasz,String javaClassFullName,String javaClassSimpleName) {
		typeMap.put(dbFieldType, 
			new JdbcTypeInformation(dbFieldType, sqlType,javaClasz, javaClassFullName, javaClassSimpleName));
	}
	
}
